import { computed, onUnmounted, reactive, ref, Ref, watch } from 'vue'
import ResizeObserver from 'resize-observer-polyfill'

/** 滚动状态 */
export default function useScrollState(scroller: Ref<HTMLElement | null> = ref(null)) {
  /** 滚动容器宽度 */
  const width = ref(0)

  /** 滚动容器高度 */
  const height = ref(0)

  /** 滚动高度 */
  const scrollHeight = ref(0)

  /** 滚动顶部距离 */
  const scrollTop = ref(0)

  /** 获取滚动容器状态 */
  function update() {
    const el = scroller.value

    if (!el) return

    state.width = el.clientWidth
    state.height = el.clientHeight
    state.scrollHeight = el.scrollHeight
    state.scrollTop = el.scrollTop
  }

  /** 滚动容器状态 */
  const state = reactive({
    /** 滚动节点 */
    scroller,

    /** 滚动容器宽度 */
    width,

    /** 滚动容器高度 */
    height,

    /** 滚动高度 */
    scrollHeight,

    /** 滚动顶部距离 */
    scrollTop,

    /** 滚动比例 */
    ratio: computed(() => {
      const ratio = scrollTop.value / (scrollHeight.value - height.value)

      if (ratio > 1) return 1

      if (ratio < 0 || Number.isNaN(ratio)) return 0

      return ratio
    }),

    /** 更新状态 */
    update
  })

  /** 监听节点 resize，更新布局 */
  const resizeObserver = new ResizeObserver(() => update())

  watch(scroller, el => {
    if (!el) return
    resizeObserver.observe(el)
    el.removeEventListener('scroll', update)
    el.addEventListener('scroll', update, { passive: true })
  })

  onUnmounted(() => {
    resizeObserver.disconnect()
    scroller.value?.removeEventListener('scroll', update)
  })

  return state
}
